package com.cxyd.modules.wms.controller;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.cxyd.common.Utils.BeanUtils;
import com.cxyd.common.Utils.ExcelUtils;
import com.cxyd.common.exception.RootException;
import com.cxyd.common.page.PageData;
import com.cxyd.common.utils.DateUtils;
import com.cxyd.common.utils.EightDigitGenerator;
import com.cxyd.common.utils.Result;
import com.cxyd.common.annotation.LogOperation;
import com.cxyd.common.validator.AssertUtils;
import com.cxyd.common.validator.ValidatorUtils;
import com.cxyd.common.validator.group.AddGroup;
import com.cxyd.common.validator.group.DefaultGroup;
import com.cxyd.common.validator.group.UpdateGroup;
import com.cxyd.modules.security.user.SecurityUser;
import com.cxyd.modules.security.user.UserDetail;
import com.cxyd.modules.wms.dto.StockDTO;
import com.cxyd.modules.wms.dto.po.StockAggregatedPo;
import com.cxyd.modules.wms.dto.po.StockSumPo;
import com.cxyd.modules.wms.dto.request.BatchForbidRequest;
import com.cxyd.modules.wms.entity.SpuEntity;
import com.cxyd.modules.wms.entity.StockEntity;
import com.cxyd.modules.wms.excel.ImportStockExcel;
import com.cxyd.modules.wms.excel.StockAggregatedExcel;
import com.cxyd.modules.wms.excel.StockExcel;
import com.cxyd.modules.wms.excel.SumStockExcel;
import com.cxyd.modules.wms.service.SpuService;
import com.cxyd.modules.wms.service.StockService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * 库存信息
 *
 * @author g_Cycle gengruyi01@163.com
 * @since 1.0.0 2023-04-27
 */
@Slf4j
@RestController
@RequestMapping("wms/stock")
public class StockController {
    private final StockService stockService;
    private final SpuService spuService;

    public StockController(StockService stockService, SpuService spuService) {
        this.stockService = stockService;
        this.spuService = spuService;
    }

    @GetMapping("page")
    @RequiresPermissions("wms:stock:page")
    public Result<PageData<StockDTO>> page(@RequestParam Map<String, Object> params) {
        PageData<StockDTO> page = stockService.page(params);

        return new Result<PageData<StockDTO>>().ok(page);
    }

    @GetMapping("checkPage")
    @RequiresPermissions("wms:stock:page")
    public Result<PageData<StockDTO>> checkPage(@RequestParam Map<String, Object> params) {
        PageData<StockDTO> page = stockService.checkPage(params);
        return new Result<PageData<StockDTO>>().ok(page);
    }

    @GetMapping("zone")
    @RequiresPermissions("wms:stock:zone")
    public Result<PageData<StockExcel>> zonePage(@RequestParam Map<String, Object> params) {
        PageData<StockExcel> page = stockService.zonePage(params);
        return new Result<PageData<StockExcel>>().ok(page);
    }

    @GetMapping("{id}")
    @RequiresPermissions("wms:stock:info")
    public Result<StockDTO> get(@PathVariable("id") Long id) {
        StockDTO data = stockService.get(id);

        return new Result<StockDTO>().ok(data);
    }

    @PostMapping
    @LogOperation("保存")
    @RequiresPermissions("wms:stock:save")
    public Result save(@RequestBody StockDTO dto) {
        //效验数据
        ValidatorUtils.validateEntity(dto, AddGroup.class, DefaultGroup.class);

        dto.setContNo(EightDigitGenerator.generateEightDigitString());
        dto.setPositionType("HW");
        dto.setStockType("B");
        stockService.save(dto);

        return new Result();
    }

    @PutMapping
    @LogOperation("修改")
    @RequiresPermissions("wms:stock:update")
    public Result update(@RequestBody StockDTO dto) {
        //效验数据
        ValidatorUtils.validateEntity(dto, UpdateGroup.class, DefaultGroup.class);

        stockService.update(dto);

        //如果库存为 0，那么就删掉此条记录
        StockEntity stockEntity = stockService.selectById(dto.getStockId());
        int stockQty = stockEntity.getStockQty().intValueExact();
        if (stockQty <= 0) {
            stockService.deleteById(stockEntity.getStockId());
        }
        return new Result();
    }

    @DeleteMapping
    @LogOperation("删除")
    @RequiresPermissions("wms:stock:delete")
    public Result delete(@RequestBody Long[] ids) {
        //效验数据
        AssertUtils.isArrayEmpty(ids, "id");

        stockService.delete(ids);

        return new Result();
    }

    @PostMapping("/disables")
    @LogOperation("一键禁用(解禁)")
    public ResponseEntity<?> disable(@RequestBody BatchForbidRequest request) {
        List<Long> ids = request.getIds(); // 获取前端传递的 ID 集合
        Integer status = request.getStatus();
        if (ids == null || ids.isEmpty()) {
            return ResponseEntity.badRequest().body("ID 集合不能为空");
        }
        try {
            // 1. 执行业务逻辑（禁用/解禁）
            stockService.stockDisables(ids, status);
            // 2. 返回成功响应
            Map<String, Object> response = new HashMap<>();
            response.put("code", 0);
            response.put("msg", "操作成功");
            return ResponseEntity.ok(response);

        } catch (Exception e) {
            // 3. 返回失败响应
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("code", 500);
            errorResponse.put("msg", "操作失败：" + e.getMessage());
            return ResponseEntity.status(500).body(errorResponse);
        }
    }

    @PostMapping("freeze/{id}")
    @LogOperation("冻结")
    public Map<String, Object> freeze(@PathVariable("id") Long stockId) {
        UserDetail user = SecurityUser.getUser();
        //效验数据
        final Map<String, Object> map = new HashMap<>();
        map.put("stockId", stockId);
        map.put("userId", user.getId());
        stockService.stockFreeze(map);
        return map;
    }

    @PostMapping("check")
    @LogOperation("盘点创建")
    public Result check(@RequestBody Map<String, Object> params) {
        UserDetail user = SecurityUser.getUser();
        params.put("userId", user.getId());
        stockService.stockCheck(params);
        //处理结果
        return new Result().ok("创建成功");
    }

    @PostMapping("outbound")
    @LogOperation("盘点出库")
    public Result outbound(@RequestBody BatchForbidRequest request) {
        List<Long> taskIds = request.getIds();
        if (ObjectUtils.isEmpty(taskIds)) {
            throw new RootException("未选择待出库任务");
        }
        try {
            for (Long taskId : taskIds) {
                Map<String, Object> params = new HashMap<>();
                params.put("taskId", taskId);
                UserDetail user = SecurityUser.getUser();
                params.put("userId", user.getId());
                stockService.outbound(params);
            }
            //处理结果
            return new Result().ok("盘点任务执行成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new Result().error("操作失败" + e.getMessage());
        }
    }

    @PostMapping("cancel")
    @LogOperation("取消盘点")
    public Result cancel(@RequestBody BatchForbidRequest request) {
        List<Long> taskIds = request.getIds();
        if (ObjectUtils.isEmpty(taskIds)) {
            throw new RootException("未选择待取消任务");
        }
        try {
            for (Long taskId : taskIds) {
                Map<String, Object> params = new HashMap<>();
                params.put("taskId", taskId);
                UserDetail user = SecurityUser.getUser();
                params.put("userId", user.getId());
                stockService.cancel(params);
            }
            //处理结果
            return new Result().ok("取消成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new Result().error("操作失败" + e.getMessage());
        }

    }

    @PostMapping("affirm")
    @LogOperation("盘点确认")
    public Result affirm(@RequestBody Map<String, Object> params) {
        return new Result().ok("success");
    }

    @PostMapping("merge-call")
    @LogOperation("合料呼叫")
    public Result mergeCall(@RequestBody Map<String, Object> params) {
        String stationNo = (String) params.get("stationNo");
        Long stockId = Long.parseLong(params.get("stockId").toString());
        if (StringUtils.isBlank(stationNo)) {
            throw new RootException("站台不能为空");
        }
        if (null == stockId) {
            throw new RootException("容器id不能为空");
        }
        UserDetail user = SecurityUser.getUser();
        params.put("userId", user.getId());
        stockService.mergeCall(params);
        return new Result().ok("success");
    }

    @GetMapping("export")
    @LogOperation("库存导出")
//    @RequiresPermissions("wcs:stock:export")
    public void export(@RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {
        List<StockDTO> list = stockService.list(params);

        // 创建StockExcel列表
        List<StockExcel> excelList = new ArrayList<>();
        for (StockDTO stockDTO : list) {
            StockExcel stockExcel = new StockExcel();
            // 复制StockDTO字段到StockExcel
            BeanUtils.copyProperties(stockDTO, stockExcel);
            // 查询 SpuEntity中的spu_spec字段并设置到StockExcel中
            SpuEntity spuEntity = spuService.getSpuBySpuNo(stockDTO.getSpuNo());
            if (spuEntity != null) {
                stockExcel.setSpuSpec(spuEntity.getSpuSpec());
                stockExcel.setSpuUnit(spuEntity.getSpuUnit());
            }
            excelList.add(stockExcel);
        }

        String currentDate = DateUtils.format(new Date());
        String fileName = "货位信息导出_" + currentDate;
        ExcelUtils.exportExcelToTarget(response, fileName, excelList, StockExcel.class);
    }

    @GetMapping("zoneExport")
    @LogOperation("平库信息导出")
    public void zoneExport(@RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {
        params.put("stock_type", "B");
        List<StockDTO> list = stockService.list(params);

        // 创建StockExcel列表
        List<StockExcel> excelList = new ArrayList<>();
        for (StockDTO stockDTO : list) {
            StockExcel stockExcel = new StockExcel();
            // 复制StockDTO字段到StockExcel
            BeanUtils.copyProperties(stockDTO, stockExcel);
            // 查询 SpuEntity中的spu_spec字段并设置到StockExcel中
            SpuEntity spuEntity = spuService.getSpuBySpuNo(stockDTO.getSpuNo());
            if (spuEntity != null) {
                stockExcel.setSpuSpec(spuEntity.getSpuSpec());
//                stockExcel.setEquipType(spuEntity.getEquipType());
                stockExcel.setSpuUnit(spuEntity.getSpuUnit());
            }
            excelList.add(stockExcel);
        }
        String currentDate = DateUtils.format(new Date());
        String fileName = "平库信息导出_" + currentDate;
        ExcelUtils.exportExcelToTarget(response, fileName, excelList, StockExcel.class);
    }

    @PostMapping("/import")
//    @RequiresPermissions("wms:stock:import")
    @LogOperation("平库信息导入")
    public Result importExcel(@RequestParam("file") MultipartFile file) {
        try {
            // 1. 校验文件
            if (file.isEmpty()) {
                return new Result().error("上传文件不能为空");
            }
            String filename = file.getOriginalFilename();
            if (!filename.endsWith(".xls") && !filename.endsWith(".xlsx")) {
                return new Result().error("仅支持 Excel 文件");
            }

            // 2. 解析 Excel
            ImportParams params = new ImportParams();
            params.setTitleRows(0); // 标题行占0行
            params.setHeadRows(1);  // 表头占1行
            List<ImportStockExcel> list = ExcelImportUtil.importExcel(
                    file.getInputStream(),
                    ImportStockExcel.class,
                    params
            );
            if (list.size() == 0) {
                return new Result().error("导入数据为空！");
            }

            // 3. 数据校验和保存
            int successCount = stockService.batchSaveOrUpdate(list);
            return new Result().success("成功导入[" + successCount + "]条数据!");
        } catch (Exception e) {
            log.error("Excel 导入失败:", e);
            return new Result().error("导入失败: " + e.getMessage());
        }
    }

    @PostMapping("error")
    @LogOperation("保存")
//    @RequiresPermissions("wms:stock:save")
    public Result errorContAdd(@RequestBody Map<String, Object> map) {

        return stockService.errorContAdd(map);
    }

    @GetMapping("bySpuNoExport")
    @LogOperation("库存导出")
//    @RequiresPermissions("wcs:stock:export")
    public void bySpuNoExport(@RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {
        List<StockAggregatedPo> list = stockService.orderBySpuNo(params);
        String currentDate = DateUtils.format(new Date());
        String fileName = "货位信息导出_" + currentDate;
        ExcelUtils.exportExcelToTarget(response, fileName, list, StockAggregatedExcel.class);
    }

    @GetMapping("byZoneNoExport")
    @LogOperation("库存导出")
//    @RequiresPermissions("wcs:stock:export")
    public void byZoneNoExport(@RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {
        List<StockAggregatedPo> list = stockService.orderByZoneNo(params);
        String currentDate = DateUtils.format(new Date());
        String fileName = "货位信息导出_" + currentDate;
        ExcelUtils.exportExcelToTarget(response, fileName, list, StockAggregatedExcel.class);
    }

    @GetMapping("sumStock")
//    @RequiresPermissions("wms:stock:page")
    public Result<PageData<StockSumPo>> sumStock(@RequestParam Map<String, Object> params) {
        PageData<StockSumPo> page = stockService.sumStock(params);

        return new Result<PageData<StockSumPo>>().ok(page);
    }

    @GetMapping("sumStockExport")
//    @RequiresPermissions("wcs:stock:export")
    public void sumStockExport(@RequestParam Map<String, Object> params, HttpServletResponse response) throws Exception {
        List<StockSumPo> list = stockService.sumStockExport(params);
        String currentDate = DateUtils.format(new Date());
        String fileName = "库存统计_" + currentDate;
        ExcelUtils.exportExcelToTarget(response, fileName, list, SumStockExcel.class);
    }

    @GetMapping("pageBySpuNo")
//    @RequiresPermissions("wms:stock:page")
    public Result<PageData<StockAggregatedPo>> pageBySpuNo(@RequestParam Map<String, Object> params) {
        PageData<StockAggregatedPo> page = stockService.pageBySpuNo(params);

        return new Result<PageData<StockAggregatedPo>>().ok(page);
    }

    @GetMapping("pageByZoneNo")
//    @RequiresPermissions("wms:stock:page")
    public Result<PageData<StockAggregatedPo>> pageByZoneNo(@RequestParam Map<String, Object> params) {
        PageData<StockAggregatedPo> page = stockService.pageByZoneNo(params);

        return new Result<PageData<StockAggregatedPo>>().ok(page);
    }
}